#
#
#
#
#
#
#
#


from CvPythonExtensions import *

import Popup as PyPopup
import CvUtil
import sys

#######SD Tool Kit#######

import SdToolKit
sdEcho         = SdToolKit.sdEcho
sdModInit      = SdToolKit.sdModInit
sdModLoad      = SdToolKit.sdModLoad
sdModSave      = SdToolKit.sdModSave
sdEntityInit   = SdToolKit.sdEntityInit
sdEntityExists = SdToolKit.sdEntityExists
sdGetVal       = SdToolKit.sdGetVal
sdSetVal       = SdToolKit.sdSetVal
sdEntityWipe   = SdToolKit.sdEntityWipe

############################

# globals
gc = CyGlobalContext()


############################################################################




###################################################################
# These methods produce messages in the log and/or on the screen. #
###################################################################
        
def logCombatMessage(ePlayer, szMessage):
        strMessage = str(szMessage)
        CyInterface().addCombatMessage(ePlayer, strMessage)

def alertActivePlayer(message, iColor = -1):

        ePlayer = gc.getGame().getActivePlayer()
        eventMessageTimeLong = gc.getDefineINT("EVENT_MESSAGE_TIME_LONG")
        szIcon = None
        iFlashX = 0
        iFlashY = 0

        szString = str(message)

        CyInterface().addMessage(ePlayer, True, eventMessageTimeLong,
                                szString, None, 0, szIcon, ColorTypes(iColor),
                                iFlashX, iFlashY, True, True)

def alertIconPlayerFortAttacks(message, pUnit, iColor = 7):

        ePlayer = gc.getGame().getActivePlayer()
        eventMessageTimeLong = gc.getDefineINT("EVENT_MESSAGE_TIME_LONG")
        szIcon = "Art/Interface/Buttons/Actions/fortify.dds"
        #iFlashX = pUnit.getX()
        #iFlashY = pUnit.getY()

        strMessage = str(message)

        CyInterface().addMessage(ePlayer, True, eventMessageTimeLong,
                                strMessage, None, 0, szIcon, ColorTypes(iColor),
                                pUnit.getX(), pUnit.getY(), True, True)

##########################################
# These are simple math related methods. #
##########################################
        
def isEqual(pPlot, pFort):
        if (pPlot == pFort):
                return True
        else:
                return False

def getPercent(num1, num2):
        onePercent = num1 / 100.0
        x = num2 / onePercent
        y = x *0.01
        return y

def getRandAttack(iSeed, iOffset):
        randSeed = CyGame().getSorenRandNum(iSeed, "Random Damage Seed")
        randOffset = CyGame().getSorenRandNum(iOffset, "Random Damage Offset")
        randDamage = randSeed - randOffset
        if (randDamage <= 0):
                return 0
        else:
                return randDamage

###################################################################
# These are the 'is' methods. Most return bool 'True' or 'False'. #
###################################################################


# This method takes plot obj and returns True if pPlot is the
# center tile of a ZoC
def isPlotZoC(pPlot):

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return False
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return False

        # If plot doesn't have ZoC data return
	if (not hasZoCPlotData(pPlot)):
                return False

        # ZoC data can be stored as True or False
        # Storing the data as False works the same as having no data
        # Is not used at the moment really, but is ment for future use
        # so forts/ect can be disabled
        strPlotID = str(pPlot.getX()) + "-" + str(pPlot.getY())

        bZoCEnabled = sdGetVal("JZoCMod", "ZoC_Plots", strPlotID)

        if (bZoCEnabled != True) and (bZoCEnabled != False):
                return False
        else:
                return bZoCEnabled
           

# This method returns True if one of the 8 tiles surronding pPlot
# is the center tile of a ZoC
# Note that pPlot itself is not checked or counted in any way
def isPlotInZoC(pPlot):

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return False
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return False

        iZoCCount = getZoCCount(pPlot)

        if (iZoCCount >= 1):
                return True
        else:
                return False

# This method takes a plot obj and an integar id of a player
# It returns Ture if pPlot is the center tile of a ZoC and also
# has units that are at war with iPlayer
def isPlotEnemyZoC(pPlot, iPlayer):

	pPlayer = gc.getPlayer(iPlayer)

	# Return immediately if the player passed in is invalid
	if (pPlayer == None):
		return False
			
	# Return immediately if the player passed in is invalid
	if (pPlayer.isNone()):
		return False

        eTeam = pPlayer.getTeam()

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return False
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return False

	# If target plot isn't a ZoC return
        if (not isPlotZoC(pPlot)):
                return False

	iEnemyUnitCount = pPlot.getNumVisibleEnemyDefenders(iPlayer)
	#iFriendlyUnitCount = pUnitPlot().getNumUnits()
	# pPlot.getUnitPower(PlayerType eOwner)
	# pPlot.isVisibleEnemyUnit(PlayerType ePlayer)
	# pPlot.isVisibleOtherUnit(PlayerType ePlayer)
	# pPlot.getBestDefender(PlayerType eOwner, PlayerType eAttackingPlayer, CyUnit pAttacker, BOOL bTestAtWar, BOOL bTestPotentialEnemy, BOOL bTestCanMove)
        #    CyUnit* (int (PlayerTypes) eOwner, int (PlayerTypes) eAttackingPlayer, CvUnit* pAttacker, bool bTestAtWar, bool bTestPotentialEnemy, bool bTestCanMove)

        # If there are no enemy units in pZoCPlot then return
        if (iEnemyUnitCount < 1):
                return False
        else:
                return True


# This method returns True if one of the 8 tiles surronding pPlot
# is the center tile of a ZoC and has units at war with iPlayer
# Note that pPlot itself is not checked or counted in any way
def isPlotInEnemyZoC(pPlot, iPlayer):

        pPlayer = gc.getPlayer(iPlayer)

	# Return immediately if the player passed in is invalid
	if (pPlayer == None):
		return False
			
	# Return immediately if the player passed in is invalid
	if (pPlayer.isNone()):
		return False

        eTeam = pPlayer.getTeam()

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return False
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return False

        iEnemyZoCCount = getEnemyZoCCount(pPlot, iPlayer)

        if (iEnemyZoCCount >= 1):
                return True
        else:
                return False


def isPlotInEnemyAndNonEnemyZoC():
        pass

        

##############################################################
# These are basic 'get' methods. They return various values. #
##############################################################



# This method starts with the number 0
# It then iterates through the 8 tiles surrounding pPlot and for
# each tile that is the center of a ZoC 1 is added to the number
# It then returns the intager number (on all failures a 0 is returned)
# Note pPlot itself is not checked or counted in any way
def getZoCCount(pPlot):

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return 0
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return 0

        iX = pPlot.getX()
	iY = pPlot.getY()

	iZoCCounter = 0

	for iiX in range(iX-1, iX+2, 1):
                for iiY in range(iY-1, iY+2, 1):
                        pPlot = CyMap().plot(iiX,iiY)
                        if (isPlotZoC(pPlot)):
                                iZoCCounter = iZoCCounter + 1

        return iZoCCounter



def getEnemyZoCCount(pPlot, iPlayer):

        pPlayer = gc.getPlayer(iPlayer)

	# Return immediately if the player passed in is invalid
	if (pPlayer == None):
		return False
			
	# Return immediately if the player passed in is invalid
	if (pPlayer.isNone()):
		return False

        eTeam = pPlayer.getTeam()

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return 0
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return 0

        iX = pPlot.getX()
	iY = pPlot.getY()

	iEnemyZoCCounter = 0

	for iiX in range(iX-1, iX+2, 1):
		for iiY in range(iY-1, iY+2, 1):
			pPlot = CyMap().plot(iiX,iiY)
			if (isPlotEnemyZoC(pPlot, iPlayer)):
                                iEnemyZoCCounter = iEnemyZoCCounter + 1

        return iEnemyZoCCounter

        

###########################################################
# These are the 'set' methods and do not return anything. #
###########################################################

def setUnitMovementFinished(pUnit):
        # To Do:
        # Make RECON immune or at most half movement
        # Make railroads bypass forts, and maybe mechanized units also

        if (not pUnit.canMove()) or (pUnit.getMoves() == 0):
                # If the unit can't move anyway, don't do anything
                return None

        pUnit.finishMoves()
        strUnitName = pUnit.getName()
        #message = "%s slowed by Zone of Control." %(strUnitName)
        #alertIconPlayerFortAttacks(message, pUnit)


        ###########################################################
        # Here are the methods used to deal with SD ToolKit data. #
        ###########################################################

def initZoCPlotDict():

        # Create the blank ZoC Plot dictionary and set it
	sdEntityInit("JZoCMod", "ZoC_Plots", {})


def checkZoCPlotDictExist():

        if (not sdEntityExists("JZoCMod", "ZoC_Plots")):
                initZoCPlotDict()

        return True


def hasZoCPlotData(pPlot):

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return False
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return False

	checkZoCPlotDictExist()

	strPlotID = str(pPlot.getX()) + "-" + str(pPlot.getY())

        hasData = None
        try:
                hasData = sdGetVal("JZoCMod", "ZoC_Plots", strPlotID)
        except:
                pass

        if (hasData == None):
                return False
        else:
                return True

def addZoCPlotData(pPlot):

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return False
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return False

	checkZoCPlotDictExist()

	strPlotID = str(pPlot.getX()) + "-" + str(pPlot.getY())

	sdSetVal("JZoCMod", "ZoC_Plots", strPlotID, True)

	return True

def delZoCPlotData(pPlot):

        # Return immediately if the plot passed in is invalid
	if (pPlot == None):
		return False
			
	# Return immediately if the plot passed in is invalid
	if (pPlot.isNone()):
		return False

	checkZoCPlotDictExist()

	strPlotID = str(pPlot.getX()) + "-" + str(pPlot.getY())
		
        sdDelVal("JZoCMod", "ZoC_Plots", strPlotID)
